import org.codehaus.groovy.grails.commons.ConfigurationHolder

import org.springframework.beans.factory.InitializingBean
import org.springframework.beans.factory.DisposableBean

import org.apache.lucene.analysis.th.ThaiAnalyzer
import org.apache.lucene.document.Document
import org.apache.lucene.document.Field
import org.apache.lucene.index.IndexWriter
import org.apache.lucene.index.IndexReader
import org.apache.lucene.index.Term
import org.apache.lucene.queryParser.QueryParser
import org.apache.lucene.search.HitCollector
import org.apache.lucene.search.IndexSearcher
import org.apache.lucene.search.TermQuery
import org.apache.lucene.search.BooleanQuery
import org.apache.lucene.search.BooleanClause
import org.apache.lucene.search.similar.MoreLikeThis
import org.apache.lucene.search.QueryFilter
import org.apache.lucene.store.FSDirectory

class PoliticIndexService implements InitializingBean {
    
    def directory
    def analyzer
    def nameEntityService
    
    void afterPropertiesSet() {
        def config = ConfigurationHolder.config
        def indexDir = new java.io.File(config.roti.index.politicDirecotry)
        def noIndex = false
        if (! indexDir.exists()) {
            indexDir.mkdirs()
            noIndex = true
        }
        directory = FSDirectory.getDirectory(indexDir)
        analyzer = new ThaiAnalyzer()
        if (noIndex) {
            // create index structure by dummy document
            def doc = new Document()
            doc.add(new Field("dummy", "", Field.Store.NO, Field.Index.UN_TOKENIZED))
            index(doc)
        }
    }
    
    def search(content, cnt=5) {
        def nms = nameEntityService.extract(content)
        def query = new BooleanQuery()
        
        nms.each() {
            def termQuery = new TermQuery(new Term('id', it.id.toString()))
            termQuery.setBoost(2)
            query.add(termQuery, BooleanClause.Occur.SHOULD)
        }
        
        extractLastName(nms).each() {
            def termQuery = new TermQuery(new Term('lastName', it))
            query.add(termQuery, BooleanClause.Occur.SHOULD)
        }
        
        def reader = IndexReader.open(directory)
        def searcher = new IndexSearcher(reader)
        def topDocs = searcher.search(query, null, cnt)
        
        def ret = []
        
        for (tmp in topDocs.scoreDocs) {
            def doc = reader.document(tmp.doc)
            ret.add([
                url: doc.get('url'),
                name: doc.get('name')
                ]);
        }
        
        return ret
    }
    
    def index(name, url, content, type = EntityType.PEOPLE) {
        def nameEntity = getOrCreateNameEntity(name, type)
        def doc = new Document()
        
        name.split('\\s').each() {
            if (it.size() > 1) { // ignore one character
                doc.add(new Field('name',
                    it,
                    Field.Store.YES,
                    Field.Index.UN_TOKENIZED))
            }
        }
        
        doc.add(new Field("id", 
                                nameEntity.id.toString(), Field.Store.YES, 
                                Field.Index.UN_TOKENIZED))
        doc.add(new Field("url", 
                                   url, Field.Store.YES, 
                                   Field.Index.UN_TOKENIZED))
        doc.add(new Field("content", 
                                     content, Field.Store.NO, 
                                     Field.Index.TOKENIZED,
                                     Field.TermVector.YES))
        
        index(doc)
    }
    
    
    def index(doc) {
        def writer  = new IndexWriter(directory, analyzer)
        try {
            writer.addDocument(doc)
        } catch (e) {
            log.error(e, e)
        }
        writer.close()
    }
    
    def getOrCreateNameEntity(name, type) {
        def nm = NameEntity.findByname(name)
        if (! nm) {
            nm = new NameEntity(name: name, type: type)
            if (!nm.save()) {
                log.error("can't create NameEntity")
                return null
            }
        }
        return nm
    }
    
    def extractLastName(names) {
        def ret = new HashSet()
        names.each() { 
            if (it.type == EntityType.PEOPLE) {
                ret.add(it.name.split(/\s+/)[-1])
            }
        }
        return ret
    }
    
    

}